package main

import "fmt"

// 如果你需要在一个对象的状态被改变时，
// 其他对象能作为其“观察者”而被通知，就可以使用观察者模式。
// 我们将自身的状态改变就会通知给其他对象的对象称为“发布者”，
// 关注发布者状态变化的对象则称为“订阅者”。

// 发布者
type Subject struct {
	observers []Observer
	content   string
}

func NewSubject() *Subject {
	return &Subject{
		observers: make([]Observer, 0),
	}
}

// 添加订阅者
func (s *Subject) AddObserver(o Observer) {
	s.observers = append(s.observers, o)
}

// 改变发布者状态
func (s *Subject) UpdateContext(content string) {
	s.content = content
	s.notify()
}

// 通知订阅者
type Observer interface {
	Do(*Subject)
}

func (s *Subject) notify() {
	for _, o := range s.observers {
		o.Do(s)
	}
}

// 订阅者
type Reader struct {
	name string
}

func NewReader(name string) *Reader {
	return &Reader{
		name: name,
	}
}
func (r *Reader) Do(s *Subject) {
	fmt.Printf("%s 订阅者收到通知：%s\n", r.name, s.content)
}

func ExampleObserver() {
	subject := NewSubject()

	boy := NewReader("小明")
	girl := NewReader("小美")

	subject.AddObserver(boy)
	subject.AddObserver(girl)

	subject.UpdateContext("hi~")
}
